home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Resources / Chat & Communication / Digsby build 37 / digsby_setup.exe / lib / pstats.pyo (.txt) < prev    next >
Python Compiled Bytecode  |  2008-10-13  |  20KB  |  701 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyo (Python 2.5)
  3.  
  4. import sys
  5. import os
  6. import time
  7. import marshal
  8. import re
  9. __all__ = [
  10.     'Stats']
  11.  
  12. class Stats:
  13.     
  14.     def __init__(self, *args, **kwds):
  15.         self.stream = sys.stdout
  16.         if 'stream' in kwds:
  17.             self.stream = kwds['stream']
  18.             del kwds['stream']
  19.         
  20.         if not len(args):
  21.             arg = None
  22.         else:
  23.             arg = args[0]
  24.             args = args[1:]
  25.         self.init(arg)
  26.         self.add(*args)
  27.  
  28.     
  29.     def init(self, arg):
  30.         self.all_callees = None
  31.         self.files = []
  32.         self.fcn_list = None
  33.         self.total_tt = 0
  34.         self.total_calls = 0
  35.         self.prim_calls = 0
  36.         self.max_name_len = 0
  37.         self.top_level = { }
  38.         self.stats = { }
  39.         self.sort_arg_dict = { }
  40.         self.load_stats(arg)
  41.         trouble = 1
  42.         
  43.         try:
  44.             self.get_top_level_stats()
  45.             trouble = 0
  46.         finally:
  47.             pass
  48.  
  49.  
  50.     
  51.     def load_stats(self, arg):
  52.         if not arg:
  53.             self.stats = { }
  54.         elif isinstance(arg, basestring):
  55.             f = open(arg, 'rb')
  56.             self.stats = marshal.load(f)
  57.             f.close()
  58.             
  59.             try:
  60.                 file_stats = os.stat(arg)
  61.                 arg = time.ctime(file_stats.st_mtime) + '    ' + arg
  62.             except:
  63.                 pass
  64.  
  65.             self.files = [
  66.                 arg]
  67.         elif hasattr(arg, 'create_stats'):
  68.             arg.create_stats()
  69.             self.stats = arg.stats
  70.             arg.stats = { }
  71.         
  72.         if not self.stats:
  73.             raise TypeError, "Cannot create or construct a %r object from '%r''" % (self.__class__, arg)
  74.         
  75.  
  76.     
  77.     def get_top_level_stats(self):
  78.         for cc, nc, tt, ct, callers in self.stats.items():
  79.             self.total_calls += nc
  80.             self.prim_calls += cc
  81.             self.total_tt += tt
  82.             if len(func_std_string(func)) > self.max_name_len:
  83.                 self.max_name_len = len(func_std_string(func))
  84.                 continue
  85.             self if callers.has_key(('jprofile', 0, 'profiler')) else self
  86.         
  87.  
  88.     
  89.     def add(self, *arg_list):
  90.         if not arg_list:
  91.             return self
  92.         
  93.         if len(arg_list) > 1:
  94.             self.add(*arg_list[1:])
  95.         
  96.         other = arg_list[0]
  97.         if type(self) != type(other) or self.__class__ != other.__class__:
  98.             other = Stats(other)
  99.         
  100.         self.files += other.files
  101.         self.total_calls += other.total_calls
  102.         self.prim_calls += other.prim_calls
  103.         self.total_tt += other.total_tt
  104.         for func in other.top_level:
  105.             self.top_level[func] = None
  106.         
  107.         self.fcn_list = None
  108.         for func, stat in other.stats.iteritems():
  109.             self.stats[func] = add_func_stats(old_func_stat, stat)
  110.         
  111.         return self
  112.  
  113.     
  114.     def dump_stats(self, filename):
  115.         f = file(filename, 'wb')
  116.         
  117.         try:
  118.             marshal.dump(self.stats, f)
  119.         finally:
  120.             f.close()
  121.  
  122.  
  123.     sort_arg_dict_default = {
  124.         'calls': (((1, -1),), 'call count'),
  125.         'cumulative': (((3, -1),), 'cumulative time'),
  126.         'file': (((4, 1),), 'file name'),
  127.         'line': (((5, 1),), 'line number'),
  128.         'module': (((4, 1),), 'file name'),
  129.         'name': (((6, 1),), 'function name'),
  130.         'nfl': (((6, 1), (4, 1), (5, 1)), 'name/file/line'),
  131.         'pcalls': (((0, -1),), 'call count'),
  132.         'stdname': (((7, 1),), 'standard name'),
  133.         'time': (((2, -1),), 'internal time') }
  134.     
  135.     def get_sort_arg_defs(self):
  136.         if not self.sort_arg_dict:
  137.             self.sort_arg_dict = dict = { }
  138.             bad_list = { }
  139.             for word, tup in self.sort_arg_dict_default.iteritems():
  140.                 fragment = word
  141.                 while fragment:
  142.                     if not fragment:
  143.                         break
  144.                     
  145.                     if fragment in dict:
  146.                         bad_list[fragment] = 0
  147.                         break
  148.                     
  149.                     dict[fragment] = tup
  150.                     fragment = fragment[:-1]
  151.             
  152.             for word in bad_list:
  153.                 del dict[word]
  154.             
  155.         
  156.         return self.sort_arg_dict
  157.  
  158.     
  159.     def sort_stats(self, *field):
  160.         if not field:
  161.             self.fcn_list = 0
  162.             return self
  163.         
  164.         if len(field) == 1 and type(field[0]) == type(1):
  165.             field = [
  166.                 {
  167.                     -1: 'stdname',
  168.                     0: 'calls',
  169.                     1: 'time',
  170.                     2: 'cumulative' }[field[0]]]
  171.         
  172.         sort_arg_defs = self.get_sort_arg_defs()
  173.         sort_tuple = ()
  174.         self.sort_type = ''
  175.         connector = ''
  176.         for word in field:
  177.             sort_tuple = sort_tuple + sort_arg_defs[word][0]
  178.             self.sort_type += connector + sort_arg_defs[word][1]
  179.             connector = ', '
  180.         
  181.         stats_list = []
  182.         for cc, nc, tt, ct, callers in self.stats.iteritems():
  183.             stats_list.append((cc, nc, tt, ct) + func + (func_std_string(func), func))
  184.         
  185.         stats_list.sort(TupleComp(sort_tuple).compare)
  186.         self.fcn_list = fcn_list = []
  187.         for tuple in stats_list:
  188.             fcn_list.append(tuple[-1])
  189.         
  190.         return self
  191.  
  192.     
  193.     def reverse_order(self):
  194.         if self.fcn_list:
  195.             self.fcn_list.reverse()
  196.         
  197.         return self
  198.  
  199.     
  200.     def strip_dirs(self):
  201.         oldstats = self.stats
  202.         self.stats = newstats = { }
  203.         max_name_len = 0
  204.         for cc, nc, tt, ct, callers in oldstats.iteritems():
  205.             newfunc = func_strip_path(func)
  206.             if len(func_std_string(newfunc)) > max_name_len:
  207.                 max_name_len = len(func_std_string(newfunc))
  208.             
  209.             newcallers = { }
  210.             for func2, caller in callers.iteritems():
  211.                 newcallers[func_strip_path(func2)] = caller
  212.             
  213.             if newfunc in newstats:
  214.                 newstats[newfunc] = add_func_stats(newstats[newfunc], (cc, nc, tt, ct, newcallers))
  215.                 continue
  216.             newstats[newfunc] = (cc, nc, tt, ct, newcallers)
  217.         
  218.         old_top = self.top_level
  219.         self.top_level = new_top = { }
  220.         for func in old_top:
  221.             new_top[func_strip_path(func)] = None
  222.         
  223.         self.max_name_len = max_name_len
  224.         self.fcn_list = None
  225.         self.all_callees = None
  226.         return self
  227.  
  228.     
  229.     def calc_callees(self):
  230.         if self.all_callees:
  231.             return None
  232.         
  233.         self.all_callees = all_callees = { }
  234.         for cc, nc, tt, ct, callers in self.stats.iteritems():
  235.             if func not in all_callees:
  236.                 all_callees[func] = { }
  237.             
  238.             for func2, caller in callers.iteritems():
  239.                 if func2 not in all_callees:
  240.                     all_callees[func2] = { }
  241.                 
  242.                 all_callees[func2][func] = caller
  243.             
  244.         
  245.  
  246.     
  247.     def eval_print_amount(self, sel, list, msg):
  248.         new_list = list
  249.         if type(sel) == type(''):
  250.             new_list = []
  251.             for func in list:
  252.                 if re.search(sel, func_std_string(func)):
  253.                     new_list.append(func)
  254.                     continue
  255.             
  256.         else:
  257.             count = len(list)
  258.             if type(sel) == type(1):
  259.                 if sel <= sel:
  260.                     pass
  261.                 elif sel < 1:
  262.                     count = int(count * sel + 0.5)
  263.                     new_list = list[:count]
  264.                 elif type(sel) == type(1):
  265.                     if sel <= sel:
  266.                         pass
  267.                     elif sel < count:
  268.                         count = sel
  269.                         new_list = list[:count]
  270.                     
  271.         if len(list) != len(new_list):
  272.             msg = msg + '   List reduced from %r to %r due to restriction <%r>\n' % (len(list), len(new_list), sel)
  273.         
  274.         return (new_list, msg)
  275.  
  276.     
  277.     def get_print_list(self, sel_list):
  278.         width = self.max_name_len
  279.         if self.fcn_list:
  280.             list = self.fcn_list[:]
  281.             msg = '   Ordered by: ' + self.sort_type + '\n'
  282.         else:
  283.             list = self.stats.keys()
  284.             msg = '   Random listing order was used\n'
  285.         for selection in sel_list:
  286.             (list, msg) = self.eval_print_amount(selection, list, msg)
  287.         
  288.         count = len(list)
  289.         if not list:
  290.             return (0, list)
  291.         
  292.         print >>self.stream, msg
  293.         if count < len(self.stats):
  294.             width = 0
  295.             for func in list:
  296.                 if len(func_std_string(func)) > width:
  297.                     width = len(func_std_string(func))
  298.                     continue
  299.             
  300.         
  301.         return (width + 2, list)
  302.  
  303.     
  304.     def print_stats(self, *amount):
  305.         for filename in self.files:
  306.             print >>self.stream, filename
  307.         
  308.         if self.files:
  309.             print >>self.stream
  310.         
  311.         indent = '        '
  312.         for func in self.top_level:
  313.             print >>self.stream, indent, func_get_function_name(func)
  314.         
  315.         print >>self.stream, indent, self.total_calls, 'function calls',
  316.         if self.total_calls != self.prim_calls:
  317.             print >>self.stream, '(%d primitive calls)' % self.prim_calls,
  318.         
  319.         print >>self.stream, 'in %.3f CPU seconds' % self.total_tt
  320.         print >>self.stream
  321.         (width, list) = self.get_print_list(amount)
  322.         if list:
  323.             self.print_title()
  324.             for func in list:
  325.                 self.print_line(func)
  326.             
  327.             print >>self.stream
  328.             print >>self.stream
  329.         
  330.         return self
  331.  
  332.     
  333.     def print_callees(self, *amount):
  334.         (width, list) = self.get_print_list(amount)
  335.         if list:
  336.             self.calc_callees()
  337.             self.print_call_heading(width, 'called...')
  338.             for func in list:
  339.                 if func in self.all_callees:
  340.                     self.print_call_line(width, func, self.all_callees[func])
  341.                     continue
  342.                 self.print_call_line(width, func, { })
  343.             
  344.             print >>self.stream
  345.             print >>self.stream
  346.         
  347.         return self
  348.  
  349.     
  350.     def print_callers(self, *amount):
  351.         (width, list) = self.get_print_list(amount)
  352.         if list:
  353.             self.print_call_heading(width, 'was called by...')
  354.             for func in list:
  355.                 (cc, nc, tt, ct, callers) = self.stats[func]
  356.                 self.print_call_line(width, func, callers, '<-')
  357.             
  358.             print >>self.stream
  359.             print >>self.stream
  360.         
  361.         return self
  362.  
  363.     
  364.     def print_call_heading(self, name_size, column_title):
  365.         print >>self.stream, 'Function '.ljust(name_size) + column_title
  366.         subheader = False
  367.         for cc, nc, tt, ct, callers in self.stats.itervalues():
  368.             if callers:
  369.                 value = callers.itervalues().next()
  370.                 subheader = isinstance(value, tuple)
  371.                 break
  372.                 continue
  373.         
  374.         if subheader:
  375.             print >>self.stream, ' ' * name_size + '    ncalls  tottime  cumtime'
  376.         
  377.  
  378.     
  379.     def print_call_line(self, name_size, source, call_dict, arrow = '->'):
  380.         print >>self.stream, func_std_string(source).ljust(name_size) + arrow,
  381.         if not call_dict:
  382.             print >>self.stream
  383.             return None
  384.         
  385.         clist = call_dict.keys()
  386.         clist.sort()
  387.         indent = ''
  388.         for func in clist:
  389.             name = func_std_string(func)
  390.             value = call_dict[func]
  391.             if isinstance(value, tuple):
  392.                 (nc, cc, tt, ct) = value
  393.                 if nc != cc:
  394.                     substats = '%d/%d' % (nc, cc)
  395.                 else:
  396.                     substats = '%d' % (nc,)
  397.                 substats = '%s %s %s  %s' % (substats.rjust(7 + 2 * len(indent)), f8(tt), f8(ct), name)
  398.                 left_width = name_size + 1
  399.             else:
  400.                 substats = '%s(%r) %s' % (name, value, f8(self.stats[func][3]))
  401.                 left_width = name_size + 3
  402.             print >>self.stream, indent * left_width + substats
  403.             indent = ' '
  404.         
  405.  
  406.     
  407.     def print_title(self):
  408.         print >>self.stream, '   ncalls  tottime  percall  cumtime  percall',
  409.         print >>self.stream, 'filename:lineno(function)'
  410.  
  411.     
  412.     def print_line(self, func):
  413.         (cc, nc, tt, ct, callers) = self.stats[func]
  414.         c = str(nc)
  415.         if nc != cc:
  416.             c = c + '/' + str(cc)
  417.         
  418.         print >>self.stream, c.rjust(9),
  419.         print >>self.stream, f8(tt),
  420.         if nc == 0:
  421.             print >>self.stream, '        ',
  422.         else:
  423.             print >>self.stream, f8(tt / nc),
  424.         print >>self.stream, f8(ct),
  425.         if cc == 0:
  426.             print >>self.stream, '        ',
  427.         else:
  428.             print >>self.stream, f8(ct / cc),
  429.         print >>self.stream, func_std_string(func)
  430.  
  431.  
  432.  
  433. class TupleComp:
  434.     
  435.     def __init__(self, comp_select_list):
  436.         self.comp_select_list = comp_select_list
  437.  
  438.     
  439.     def compare(self, left, right):
  440.         for index, direction in self.comp_select_list:
  441.             l = left[index]
  442.             r = right[index]
  443.             if l < r:
  444.                 return -direction
  445.             
  446.             if l > r:
  447.                 return direction
  448.                 continue
  449.         
  450.         return 0
  451.  
  452.  
  453.  
  454. def func_strip_path(func_name):
  455.     (filename, line, name) = func_name
  456.     return (os.path.basename(filename), line, name)
  457.  
  458.  
  459. def func_get_function_name(func):
  460.     return func[2]
  461.  
  462.  
  463. def func_std_string(func_name):
  464.     if func_name[:2] == ('~', 0):
  465.         name = func_name[2]
  466.         if name.startswith('<') and name.endswith('>'):
  467.             return '{%s}' % name[1:-1]
  468.         else:
  469.             return name
  470.     else:
  471.         return '%s:%d(%s)' % func_name
  472.  
  473.  
  474. def add_func_stats(target, source):
  475.     (cc, nc, tt, ct, callers) = source
  476.     (t_cc, t_nc, t_tt, t_ct, t_callers) = target
  477.     return (cc + t_cc, nc + t_nc, tt + t_tt, ct + t_ct, add_callers(t_callers, callers))
  478.  
  479.  
  480. def add_callers(target, source):
  481.     new_callers = { }
  482.     for func, caller in target.iteritems():
  483.         new_callers[func] = caller
  484.     
  485.     for func, caller in source.iteritems():
  486.         if func in new_callers:
  487.             new_callers[func] = caller + new_callers[func]
  488.             continue
  489.         new_callers[func] = caller
  490.     
  491.     return new_callers
  492.  
  493.  
  494. def count_calls(callers):
  495.     nc = 0
  496.     for calls in callers.itervalues():
  497.         nc += calls
  498.     
  499.     return nc
  500.  
  501.  
  502. def f8(x):
  503.     return '%8.3f' % x
  504.  
  505. if __name__ == '__main__':
  506.     import cmd
  507.     
  508.     try:
  509.         import readline
  510.     except ImportError:
  511.         pass
  512.  
  513.     
  514.     class ProfileBrowser(cmd.Cmd):
  515.         
  516.         def __init__(self, profile = None):
  517.             cmd.Cmd.__init__(self)
  518.             self.prompt = '% '
  519.             if profile is not None:
  520.                 self.stats = Stats(profile)
  521.                 self.stream = self.stats.stream
  522.             else:
  523.                 self.stats = None
  524.                 self.stream = sys.stdout
  525.  
  526.         
  527.         def generic(self, fn, line):
  528.             args = line.split()
  529.             processed = []
  530.             for term in args:
  531.                 
  532.                 try:
  533.                     processed.append(int(term))
  534.                 except ValueError:
  535.                     pass
  536.  
  537.                 
  538.                 try:
  539.                     frac = float(term)
  540.                     if frac > 1 or frac < 0:
  541.                         print >>self.stream, 'Fraction argument must be in [0, 1]'
  542.                         continue
  543.                     
  544.                     processed.append(frac)
  545.                 except ValueError:
  546.                     pass
  547.  
  548.                 processed.append(term)
  549.             
  550.             if self.stats:
  551.                 getattr(self.stats, fn)(*processed)
  552.             else:
  553.                 print >>self.stream, 'No statistics object is loaded.'
  554.             return 0
  555.  
  556.         
  557.         def generic_help(self):
  558.             print >>self.stream, 'Arguments may be:'
  559.             print >>self.stream, '* An integer maximum number of entries to print.'
  560.             print >>self.stream, '* A decimal fractional number between 0 and 1, controlling'
  561.             print >>self.stream, '  what fraction of selected entries to print.'
  562.             print >>self.stream, '* A regular expression; only entries with function names'
  563.             print >>self.stream, '  that match it are printed.'
  564.  
  565.         
  566.         def do_add(self, line):
  567.             self.stats.add(line)
  568.             return 0
  569.  
  570.         
  571.         def help_add(self):
  572.             print >>self.stream, 'Add profile info from given file to current statistics object.'
  573.  
  574.         
  575.         def do_callees(self, line):
  576.             return self.generic('print_callees', line)
  577.  
  578.         
  579.         def help_callees(self):
  580.             print >>self.stream, 'Print callees statistics from the current stat object.'
  581.             self.generic_help()
  582.  
  583.         
  584.         def do_callers(self, line):
  585.             return self.generic('print_callers', line)
  586.  
  587.         
  588.         def help_callers(self):
  589.             print >>self.stream, 'Print callers statistics from the current stat object.'
  590.             self.generic_help()
  591.  
  592.         
  593.         def do_EOF(self, line):
  594.             print >>self.stream, ''
  595.             return 1
  596.  
  597.         
  598.         def help_EOF(self):
  599.             print >>self.stream, 'Leave the profile brower.'
  600.  
  601.         
  602.         def do_quit(self, line):
  603.             return 1
  604.  
  605.         
  606.         def help_quit(self):
  607.             print >>self.stream, 'Leave the profile brower.'
  608.  
  609.         
  610.         def do_read(self, line):
  611.             if line:
  612.                 
  613.                 try:
  614.                     self.stats = Stats(line)
  615.                 except IOError:
  616.                     args = None
  617.                     print >>self.stream, args[1]
  618.                     return None
  619.  
  620.                 self.prompt = line + '% '
  621.             elif len(self.prompt) > 2:
  622.                 line = self.prompt[-2:]
  623.             else:
  624.                 print >>self.stream, 'No statistics object is current -- cannot reload.'
  625.             return 0
  626.  
  627.         
  628.         def help_read(self):
  629.             print >>self.stream, 'Read in profile data from a specified file.'
  630.  
  631.         
  632.         def do_reverse(self, line):
  633.             self.stats.reverse_order()
  634.             return 0
  635.  
  636.         
  637.         def help_reverse(self):
  638.             print >>self.stream, 'Reverse the sort order of the profiling report.'
  639.  
  640.         
  641.         def do_sort(self, line):
  642.             abbrevs = self.stats.get_sort_arg_defs()
  643.             if line and not filter((lambda x, a = abbrevs: x not in a), line.split()):
  644.                 self.stats.sort_stats(*line.split())
  645.             else:
  646.                 print >>self.stream, 'Valid sort keys (unique prefixes are accepted):'
  647.                 for key, value in Stats.sort_arg_dict_default.iteritems():
  648.                     print >>self.stream, '%s -- %s' % (key, value[1])
  649.                 
  650.             return 0
  651.  
  652.         
  653.         def help_sort(self):
  654.             print >>self.stream, 'Sort profile data according to specified keys.'
  655.             print >>self.stream, "(Typing `sort' without arguments lists valid keys.)"
  656.  
  657.         
  658.         def complete_sort(self, text, *args):
  659.             return _[1]
  660.  
  661.         
  662.         def do_stats(self, line):
  663.             return self.generic('print_stats', line)
  664.  
  665.         
  666.         def help_stats(self):
  667.             print >>self.stream, 'Print statistics from the current stat object.'
  668.             self.generic_help()
  669.  
  670.         
  671.         def do_strip(self, line):
  672.             self.stats.strip_dirs()
  673.             return 0
  674.  
  675.         
  676.         def help_strip(self):
  677.             print >>self.stream, 'Strip leading path information from filenames in the report.'
  678.  
  679.         
  680.         def postcmd(self, stop, line):
  681.             if stop:
  682.                 return stop
  683.             
  684.  
  685.  
  686.     import sys
  687.     if len(sys.argv) > 1:
  688.         initprofile = sys.argv[1]
  689.     else:
  690.         initprofile = None
  691.     
  692.     try:
  693.         browser = ProfileBrowser(initprofile)
  694.         print >>browser.stream, 'Welcome to the profile statistics browser.'
  695.         browser.cmdloop()
  696.         print >>browser.stream, 'Goodbye.'
  697.     except KeyboardInterrupt:
  698.         pass
  699.  
  700.  
  701.